package sk.atletis.atletika;

import java.util.Date;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;

public class AtletikaProvider extends ContentProvider 
{
	public static final String AUTHORITY = "sk.atletis.atletika.provider";
	public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);
	
	private static final int ARTICLES = 0;
	private static final int ARTICLE_ID = 1;
	
	private static final int COMPETITIONS = 2;
	private static final int COMPETITION_ID = 3;
	
	private static final String[] ARTICLES_MANDATORY_COLUMNS = { 
		ArticlesContract.CATEGORYID, 
		ArticlesContract.TITLE 
		};
	
	protected static final String DATABASE_NAME = "atletis";
	protected static final int DATABASE_VERSION = 2;
	
	protected static final String TB_ARTICLES = "articles";
	protected static final String TB_COMPETITIONS = "competitions";
	
	private SQLiteOpenHelper sqlHelper;
	
	private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
	static 
	{
		uriMatcher.addURI(AUTHORITY, ArticlesContract.ARTICLES, ARTICLES);
		uriMatcher.addURI(AUTHORITY, ArticlesContract.ARTICLES + "/#", ARTICLE_ID);
		
		uriMatcher.addURI(AUTHORITY, CompetitionsContract.COMPETITIONS, COMPETITIONS);
		uriMatcher.addURI(AUTHORITY, CompetitionsContract.COMPETITIONS + "/#", COMPETITION_ID);
	}
	
	// Database Helper
	static class DatabaseHelper extends SQLiteOpenHelper 
	{
		// Constructor
		DatabaseHelper(Context context) 
		{
			super(context, DATABASE_NAME, null, DATABASE_VERSION);
		}

		@Override
		public void onCreate(SQLiteDatabase db) 
		{
			// Create table ARTICLES
			String sql = "CREATE TABLE " + TB_ARTICLES + " "
					+ "(" 
					+ ArticlesContract._ID + " INTEGER PRIMARY KEY,"
					+ ArticlesContract.CATEGORYID + " INTEGER NULL,"
					+ ArticlesContract.TITLE + " TEXT NULL,"
					+ ArticlesContract.CITY + " TEXT NULL,"
					+ ArticlesContract.DATE + " TEXT NULL,"
					+ ArticlesContract.EDITOR + " TEXT NULL,"
					+ ArticlesContract.PEREX + " TEXT NULL,"
					+ ArticlesContract.ARTICLETEXT + " TEXT NULL,"
					+ ArticlesContract.IMAGEPATH + " TEXT NULL,"
					+ ArticlesContract.IMAGETEXT + " TEXT NULL,"
					+ ArticlesContract.IMAGEFILE + " BLOB NULL,"
					+ ArticlesContract.VIEWED + " BOOLEAN NOT NULL DEFAULT 0," 
					+ ArticlesContract.ADDED + " INTEGER NULL"
					+ ");";
			db.execSQL(sql);
			
			sql = "CREATE TABLE " + TB_COMPETITIONS + " "
					+ "("
					+ CompetitionsContract._ID + " INTEGER PRIMARY KEY,"
					+ CompetitionsContract.NAME + " TEXT NULL,"
					+ CompetitionsContract.DATE_FROM + " TEXT NULL,"
					+ CompetitionsContract.CITY + " TEXT NULL,"
					+ CompetitionsContract.RESULTS_PATH + " TEXT NULL,"
					+ CompetitionsContract.ADDED + " INTEGER NULL"
					+ ");";
			db.execSQL(sql);
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 
		{
			db.execSQL("DROP TABLE IF EXISTS " + TB_ARTICLES);
			db.execSQL("DROP TABLE IF EXISTS " + TB_COMPETITIONS);
			onCreate(db);
		}
	}
	
	// -- Provider methods --
	
	@Override
	public boolean onCreate() 
	{
		this.sqlHelper = new DatabaseHelper(getContext());
		return true;
	}
	
	@Override
	public Uri insert(Uri uri, ContentValues values)
	{
		SQLiteDatabase db = sqlHelper.getWritableDatabase();
		long id = 0;
		
		switch (uriMatcher.match(uri)) 
		{
		
		case ARTICLES:
			checkArticlesColumns(values);
			
			// Was viewed?
			if (!values.containsKey(ArticlesContract.VIEWED))
				values.put(ArticlesContract.VIEWED, false);

			// Added
			if (!values.containsKey(ArticlesContract.ADDED))
				values.put(ArticlesContract.ADDED, new Date().getTime());
			
			// Insert
			id = db.insert(TB_ARTICLES, null, values);
			
			// Return inserted URI
			if (id > 0) 
			{
				Uri noteUri = ContentUris.withAppendedId(ArticlesContract.CONTENT_URI_ARTICLES, id);
				getContext().getContentResolver().notifyChange(noteUri, null);
				return noteUri;
			} 
			else 
			{
				return null;
			}
			
		case COMPETITIONS:
			
			// Added
			if (!values.containsKey(CompetitionsContract.ADDED))
				values.put(CompetitionsContract.ADDED, new Date().getTime());
			
			// Insert
			id = db.insert(TB_COMPETITIONS, null, values);
			
			// Return inserted URI
			if (id > 0) 
			{
				Uri competitionUri = ContentUris.withAppendedId(CompetitionsContract.CONTENT_URI_COMPETITIONS, id);
				getContext().getContentResolver().notifyChange(competitionUri, null);
				return competitionUri;
			} 
			else 
			{
				return null;
			}
		
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
		
		
	}
	
	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) 
	{
		SQLiteDatabase db = sqlHelper.getWritableDatabase();

		int count;

		switch (uriMatcher.match(uri)) 
		{
		case ARTICLES:
			count = db.delete(TB_ARTICLES, selection, selectionArgs);
			break;

		case ARTICLE_ID:
			String[] newArgs = createSelectionArgsWithId(selectionArgs, uri.getPathSegments().get(1));
			String where = createSelectionWithId(selection);
			count = db.delete(TB_ARTICLES, where, newArgs);
			break;

		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}

		// Returns number of deleted
		return count;
	}
	
	@Override
	public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) 
	{
		SQLiteDatabase db = sqlHelper.getWritableDatabase();

		int count = 0;

		switch (uriMatcher.match(uri)) 
		{
		case ARTICLES:
			count = db.update(TB_ARTICLES, values, selection, selectionArgs);
			break;

		case ARTICLE_ID:
			String[] newArgs = createSelectionArgsWithId(selectionArgs, uri.getPathSegments().get(1));
			String where = createSelectionWithId(selection);
			count = db.update(TB_ARTICLES, values, where, newArgs);
			break;
			
		case COMPETITIONS:
			count = db.update(TB_COMPETITIONS, values, selection, selectionArgs);
			break;
			
		case COMPETITION_ID:
			String[] newArgsCompetition = createSelectionArgsWithId(selectionArgs, uri.getPathSegments().get(1));
			String whereCompetition = createSelectionWithId(selection);
			count = db.update(TB_COMPETITIONS, values, whereCompetition, newArgsCompetition);
			break;

		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}

		//sendUpdateBroadcast(count);
		//getContext().getContentResolver().notifyChange(uri, null);

		return count;
	}
	
	@Override
	public String getType(Uri uri) 
	{
		switch (uriMatcher.match(uri)) 
		{
		case ARTICLES:
			return ArticlesContract.MIME_TYPE_DIR;

		case ARTICLE_ID:
			return ArticlesContract.MIME_TYPE_ITEM;
			
		case COMPETITIONS:
			return CompetitionsContract.MIME_TYPE_DIR;
			
		case COMPETITION_ID:
			return CompetitionsContract.MIME_TYPE_ITEM;

		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
	}
	
	@Override
	public Cursor query(Uri uri, String[] projection, String selection,	String[] selectionArgs, String sortOrder) 
	{
		SQLiteDatabase db = sqlHelper.getReadableDatabase();

		if (sortOrder == null || sortOrder.equals(""))
			sortOrder = ArticlesContract.SORT_DEFAULT;

		switch (uriMatcher.match(uri)) 
		{
		case ARTICLES:
		case COMPETITIONS:
			break;

		case ARTICLE_ID:
		case COMPETITION_ID:
			selectionArgs = createSelectionArgsWithId(selectionArgs, uri.getPathSegments().get(1));
			selection = createSelectionWithId(selection);
			break;

		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}

		switch (uriMatcher.match(uri)) 
		{
		case ARTICLES:
			Cursor cArt = db.query(TB_ARTICLES, projection, selection, selectionArgs, null, null, sortOrder);
			cArt.setNotificationUri(getContext().getContentResolver(), uri);
			return cArt;
			
		case COMPETITIONS:
			Cursor cComp = db.query(TB_COMPETITIONS, projection, selection, selectionArgs, null, null, sortOrder);
			cComp.setNotificationUri(getContext().getContentResolver(), uri);
			return cComp;
			
		default:
				return null;
		}
	}
	
	@Override
	public int bulkInsert(Uri uri, ContentValues[] values) 
	{
		int insertCount = 0;
		
		switch (uriMatcher.match(uri)) 
		{
		case ARTICLES:
		case COMPETITIONS:
			break;

		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}

		for (ContentValues v : values)
		{
			if (insert(uri, v) != null)
				insertCount++;
		}

		if (uriMatcher.match(uri) == ARTICLES)
		{
			sendUpdateBroadcast(insertCount);
		}

		return insertCount;
	}
	
	// -- Next methods --
	
	private void checkArticlesColumns(ContentValues values) 
	{
		for (String key : ARTICLES_MANDATORY_COLUMNS) 
		{
			if (!values.containsKey(key)) 
			{
				throw new NullPointerException("ContentValues must contain key " + key);
			}
		}
	}
	
	// Returns array which is copy of origin with id on last position
	private String[] createSelectionArgsWithId(String[] oldArgs, String id) 
	{
		String[] newArgs;
		if (oldArgs != null)
			newArgs = copyOfArray(oldArgs, oldArgs.length + 1);
		else
			newArgs = new String[1];

		newArgs[newArgs.length - 1] = id;
		return newArgs;
	}
	
	// Returns array with length + 1
	private static String[] copyOfArray(String[] old, int newLength) 
	{
		String[] newArray = new String[newLength];

		int oldLength = old.length;

		for (int i = 0; i < Math.min(oldLength, newLength); i++) 
		{
			if (i < oldLength)
				newArray[i] = old[i];
			else
				newArray[i] = null;
		}

		return newArray;
	}
	
	// Returns selection string with ID on the end
	private String createSelectionWithId(String oldSelection) 
	{
		String where = ArticlesContract._ID + " = ?";

		if (oldSelection != null && !oldSelection.equals("")) 
		{
			where = oldSelection + " AND " + where;
		}

		return where;
	}
	
	// Sends update broadcast action
	private void sendUpdateBroadcast(int count) 
	{
		if (count > 0)
		{
			Intent i = new Intent(ArticlesContract.ACTION_ARTICLES_UPDATED);
			i.putExtra(ArticlesContract.NEW_ARTICLES, count);
			getContext().sendBroadcast(i);
		}
	}
	
	
	
}
